﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using Isuka.Iteration;

namespace Isuka.Spiritual
{
    /// <summary>
    /// ルールコンテキスト
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="A"></typeparam>
    public sealed class RuleContext<T, A>
        where T : IEquatable<T>
        where A : class
    {
        public readonly IBidirectionalIterator<T> First;

        public readonly IBidirectionalIterator<T> Last;

        public readonly A Argument;

        public RuleContext(IBidirectionalIterator<T> first, IBidirectionalIterator<T> last, A arg)
        {
            Contract.Requires<ArgumentNullException>(first != null, "first");

            this.First = first.Copy();
            if (last != null)
            {
                this.Last = last.Copy();
            }
            this.Argument = arg;
        }

        public RuleContext<T, NA> RebindArg<NA>(NA arg)
            where NA : class
        {
            return new RuleContext<T, NA>(First, Last, arg);
        }

        #region ContractInvariantMethod

        [ContractInvariantMethod]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Required for code contracts.")]
        private void ObjectInvariant()
        {
            Contract.Invariant(First != null);
        }

        #endregion
    }
}
